package com.ml.utils.httpclient;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;

import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import lombok.extern.slf4j.Slf4j;  
  
/** 
 * HTTP 请求工具类 
 * 支持SSL、代理
 * @author : zzy 
 * @version : 2.0.0 
 * @date : 2019/07/01 
 * @see : 整合了HttpClientUtil中建立SSl链接配置和SocketConfig、HttpPoolUtil连接池的操作。
 */  
@Slf4j
public class HttpPoolUtil {  
    public static volatile boolean isClosed = false;
	
    private static PoolingHttpClientConnectionManager poolConnManager;  
    private static RequestConfig requestConfig;  
    private static final int MAX_CONNECTION_TOTA = 1000;
    private static final int ROUTE_MAX_COUNT = 800;
    
    private static final int CONNECTION_TIME_OUT = 5000;
    private static final int READ_TIME_OUT = 3000;
    private static final int REQUEST_TIMEOUT = 3000;
    
    private static final int RETRYNUMS = 1;
    private static HttpClientBuilder httpClientBuilder;

    static {
    	RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
		registryBuilder.register("http", PlainConnectionSocketFactory.INSTANCE).build();
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
			TrustStrategy anyTrustStrategy = new TrustStrategy() {
				public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
					return true;
				}
			};
			SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, anyTrustStrategy)
					.build();
			/* -- old 
			 * SSLContext sslContext = SSLContexts.custom().
					.useTLS().loadTrustMaterial(trustStore, anyTrustStrategy)
					.build();
			 */
			LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext,
					SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			registryBuilder.register("https", sslSF);
		} catch (Exception e) {

		}
		Registry<ConnectionSocketFactory> registry = registryBuilder.build();
    	
		ConnectionKeepAliveStrategy kaStrategy = new ConnectionKeepAliveStrategy() {
		    public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
		        HeaderElementIterator it = new BasicHeaderElementIterator
		            (response.headerIterator(HTTP.CONN_KEEP_ALIVE));
		        while (it.hasNext()) {
		            HeaderElement he = it.nextElement();
		            String param = he.getName();
		            String value = he.getValue();
		            if (value != null && param.equalsIgnoreCase
		               ("timeout")) {
		                return Long.parseLong(value) * 1000;
		            }
		        }
		        return 60 * 1000;//如果没有约定，则默认定义时长为60s
		    }
		};
		
		
        // 设置连接池  
//    	poolConnManager = new PoolingHttpClientConnectionManager(registry);  
    	poolConnManager = new PoolingHttpClientConnectionManager();  
    	ConnectionConfig connectionConfig = ConnectionConfig.custom().setCharset(Consts.UTF_8).build();//重定向获取的url转码
//    	ConnectionConfig.custom().setCharset(Charset.forName("UTF-8")).build();

//		SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).setSoKeepAlive(true)
//				.setSoReuseAddress(true).setSoTimeout(1000).build();
		
		poolConnManager.setDefaultConnectionConfig(connectionConfig);
//		poolConnManager.setDefaultSocketConfig(socketConfig);
        // 设置连接池大小  
    	poolConnManager.setMaxTotal(MAX_CONNECTION_TOTA);  
    	poolConnManager.setDefaultMaxPerRoute(ROUTE_MAX_COUNT);  

    	
        RequestConfig.Builder configBuilder = RequestConfig.custom();  
        // 设置连接超时  
        configBuilder.setConnectTimeout(CONNECTION_TIME_OUT);  
        // 设置读取超时  
        configBuilder.setSocketTimeout(READ_TIME_OUT);  
        // 设置从连接池获取连接实例的超时  
        configBuilder.setConnectionRequestTimeout(REQUEST_TIMEOUT);  
        // 在提交请求之前 测试连接是否可用  
//        configBuilder.setStaleConnectionCheckEnabled(true);  
        // 禁止自动重定向//TODO
        configBuilder.setRedirectsEnabled(false);

        requestConfig = configBuilder.build(); 
        httpClientBuilder = HttpClients.custom().
        		setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()).
        		setConnectionManager(poolConnManager).
        		setDefaultRequestConfig(requestConfig).
        		setKeepAliveStrategy(kaStrategy);
        	     // 设置重试次数(好像不针对超时重试？)
//                .setRetryHandler(new DefaultHttpRequestRetryHandler(RETRYNUMS, false))
        System.out.println(">>>>>>>>>>>> PoolingHttpClientConnectionManager初始化成功 <<<<<<<<<<<<<<");
    }  
  
    /**
     * 获取HttpClient客户端
     * @return httpClient
     */
    public static CloseableHttpClient getClient() {
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(poolConnManager)
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(RETRYNUMS, false))
                .build();

        if (poolConnManager != null && poolConnManager.getTotalStats() != null){
        	System.out.println("now client pool:{}"+poolConnManager.getTotalStats().toString());
        }
        if( null == httpClient){
            httpClient = HttpClients.createDefault();
        }
        return httpClient;
    }
    

    /**
     * 从http连接池里获取客户端实例
     * CloseableHttpResponse response = HttpPoolUtil.getClient().execute(httpGet);
     * @return httpClient
     */
    public static CloseableHttpClient getHttpClient() {
        CloseableHttpClient httpClient = httpClientBuilder.build();
        if( null == httpClient ){
            httpClient = HttpClients.createDefault();
        }
        return httpClient;
    }

    /**
     * 关闭连接池资源
     */
    public static void closePool() {
        if( !isClosed ){
            isClosed = true;
            poolConnManager.close();
        }
    }
    
    /** 
     * 发送 GET 请求（HTTP），不带输入数据 
     * @param url 
     * @return 
     */  
    public static String doGet(String url, boolean isSSL) {  
        return doGet(url, new HashMap<String, Object>(), isSSL);  
    }  
    
    /** 
     * 发送 GET 请求（HTTP），K-V形式 
     * @param url 
     * @param params 
     * @return 
     */  
    public static String doGet(String url, Map<String, Object> params, boolean isSSL) {  
        String apiUrl = url;  
        StringBuffer param = new StringBuffer();  
        int i = 0;  
        for (String key : params.keySet()) {  
            if (i == 0)  
                param.append("?");  
            else  
                param.append("&");  
            param.append(key).append("=").append(params.get(key));  
            i++;  
        }  
        apiUrl += param;  
        String result = null; 
        CloseableHttpClient httpClient = null;
        if(isSSL) {
        	httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
    				.setConnectionManager(poolConnManager)
    				.setDefaultRequestConfig(requestConfig).build(); 
        }else {
        	httpClient = getHttpClient();  
        }
        HttpGet httpGet = null;
        try {  
        	httpGet = new HttpGet(apiUrl);  
            HttpResponse response = httpClient.execute(httpGet);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doGet statusCode:{},url:{}",statusCode,url);  
  
            HttpEntity entity = response.getEntity();  
            if (entity != null) {  
                InputStream instream = entity.getContent();  
                result = IOUtils.toString(instream, "UTF-8");  
            }  
        } catch (IOException e) {
			log.error("retry one times,getJSON exception:{} url:{}?{}", e.getMessage(),url,params);
			try {
				httpGet = new HttpGet(apiUrl);  
				HttpResponse response = httpClient.execute(httpGet);  
				
				HttpEntity entity = response.getEntity();  
				if (entity != null) {  
					InputStream instream = entity.getContent();  
					result = IOUtils.toString(instream, "UTF-8");  
				}
				
			} catch (Exception e2) {
				e2.printStackTrace();  
			}  

        } finally {
        	if(httpGet!=null) {
        		httpGet.releaseConnection();
        	}
        } 
        return result;  
    }  
  
    /** 
     * 发送 GET 请求（HTTP），K-V形式 ，代理模式
     * @param url 
     * @param params 
     * @return 
     */  
    public static String doGet(String url, Map<String, Object> params, Map<String, String> header, 
    		String proxyHost, int proxyPort,  boolean isSSL) {  
        String apiUrl = url;  
        StringBuffer param = new StringBuffer();  
        int i = 0;  
        if(params!=null) {
        	for (String key : params.keySet()) {  
        		if (i == 0)  
        			param.append("?");  
        		else  
        			param.append("&");  
        		param.append(key).append("=").append(params.get(key));  
        		i++;  
        	}  
        }
        apiUrl += param;  
        String result = null;  
        HttpClient httpClient = null;
        if(proxyHost!=null&&!"".equals(proxyHost)&&proxyPort>0) {
        	 if(isSSL) {
             	httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
         				.setConnectionManager(poolConnManager)
         				.setDefaultRequestConfig(requestConfig)
         				.setProxy(new HttpHost(proxyHost, proxyPort)).build(); 
             	
             }else {
             	httpClient = HttpClients.custom()
             			.setConnectionManager(poolConnManager)
        				.setDefaultRequestConfig(requestConfig)
        				.setProxy(new HttpHost(proxyHost, proxyPort)).build();
             }
        } else {
            if(isSSL) {
            	httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
        				.setConnectionManager(poolConnManager)
        				.setDefaultRequestConfig(requestConfig).build(); 
            }else {
            	httpClient = getHttpClient();  
            }
        }
        HttpGet httpGet = null;
        try {  
        	httpGet = new HttpGet(apiUrl);
            if(header!=null) {
            	for (String key : header.keySet()) {
            		httpGet.addHeader(key, header.get(key));	
            	}
            }
            HttpResponse response = httpClient.execute(httpGet);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doGet statusCode:{},url:{}",statusCode,apiUrl);   
            HttpEntity entity = response.getEntity();  
            if (entity != null) {  
                InputStream instream = entity.getContent();  
                result = IOUtils.toString(instream, "UTF-8");  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {
        	if(httpGet!=null) {
        		httpGet.releaseConnection();
        	}
        }
        return result;  
    }   
    
    /** 
     * 发送 GET 请求（HTTP），K-V形式 ，代理模式
     * @param url 
     * @param params 
     * @return 
     */  
    public static String doGetReturnForwardURl(String url, Map<String, Object> params, Map<String, String> header, 
    		String proxyHost, int proxyPort,  boolean isSSL) {  
        String apiUrl = url;  
        StringBuffer param = new StringBuffer();  
        String newUrl = "";
        int i = 0;  
        if(params!=null) {
        	for (String key : params.keySet()) {  
        		if (i == 0)  
        			param.append("?");  
        		else  
        			param.append("&");  
        		param.append(key).append("=").append(params.get(key));  
        		i++;  
        	}  
        }
        apiUrl += param;  
        String result = null;  
        HttpClient httpClient = null;
        if(proxyHost!=null&&!"".equals(proxyHost)&&proxyPort>0) {
        	 if(isSSL) {
             	httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
         				.setConnectionManager(poolConnManager)
         				.setDefaultRequestConfig(requestConfig)
         				.setProxy(new HttpHost(proxyHost, proxyPort)).build(); 
             	
             }else {
             	httpClient = HttpClients.custom()
             			.setConnectionManager(poolConnManager)
        				.setDefaultRequestConfig(requestConfig)
        				.setProxy(new HttpHost(proxyHost, proxyPort)).build();
             }
        } else {
            if(isSSL) {
            	httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
        				.setConnectionManager(poolConnManager)
        				.setDefaultRequestConfig(requestConfig).build(); 
            }else {
            	httpClient = getHttpClient();  
            }
        }
        HttpGet httpGet = null;
        try {  
        	httpGet = new HttpGet(apiUrl);
            if(header!=null) {
            	for (String key : header.keySet()) {
            		httpGet.addHeader(key, header.get(key));	
            	}
            }
            HttpResponse response = httpClient.execute(httpGet);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doGet statusCode:{},url:{}",statusCode,apiUrl);  
            
            if(302==statusCode) {
            	Header responseHeader = response.getFirstHeader("location"); // 跳转的目标地址是在 HTTP-HEAD 中的
            	newUrl = responseHeader.getValue(); // 这就是跳转后的地址，再向这个地址发出新申请，以便得到跳转后的信息是啥。
//                System.out.println(newUrl);
                return newUrl;
            }
            
//            HttpEntity entity = response.getEntity();  
//            if (entity != null) {  
//                InputStream instream = entity.getContent();  
//                result = IOUtils.toString(instream, "UTF-8");  
//            }  
        } catch (IOException e) {  
        	log.info("error url="+apiUrl);
            e.printStackTrace(); 
        } finally {
        	if(httpGet!=null) {
        		httpGet.releaseConnection();
        	}
        }
//        return result; 
        return newUrl;
    }   
    
    /** 
     * 发送 POST 请求（HTTP），不带输入数据 
     * @param apiUrl 
     * @return 
     */  
    public static String doPost(String apiUrl) {  
        return doPost(apiUrl, new HashMap<String, Object>());  
    }  
  
    /** 
     * 发送 POST 请求（HTTP），K-V形式  ,application/x-www-form-urlencoded
     * @param apiUrl API接口URL 
     * @param params 参数map 
     * @return 
     */  
    public static String doFormUrlEncodedPost(String apiUrl, Map<String, Object> params, Map<String,Object> headerMap) {  
        CloseableHttpClient httpClient = getHttpClient();  
        String httpStr = null;  
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size());  
            for (Map.Entry<String, Object> entry : params.entrySet()) {  
                NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry  
                        .getValue().toString());  
                pairList.add(pair);  
            }  
            httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8")));  
            if(headerMap!=null) {
            	for(String key:headerMap.keySet()){
            		httpPost.setHeader(key, headerMap.get(key).toString());
            	}
            }
            response = httpClient.execute(httpPost);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doPost statusCode:{},url:{}",statusCode,apiUrl); 
            HttpEntity entity = response.getEntity();  
            httpStr = EntityUtils.toString(entity, "UTF-8");  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            } 
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return httpStr;  
    }  
    
    /** 
     * 发送  POST 请求（HTTPS/HTTP），模拟表单提交，multipart/form-data，header内不用再添加content-type
     * @param apiUrl API接口URL 
     * @param
     * @return 
     */  
    @SuppressWarnings("deprecation")
	public static String doFormDataPost(boolean isSSL,String apiUrl,Map<String, Object> params, Map<String,Object> headerMap) {  
    	CloseableHttpClient httpClient = null;
    	if(isSSL) {
    		httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
    				.setConnectionManager(poolConnManager)
    				.setDefaultRequestConfig(requestConfig).build();  
    	}else {
    		httpClient = getHttpClient(); 
    	}
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
        String content = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);  
            for (String key : params.keySet()) {
            	builder.addPart(key, new StringBody(params.get(key).toString(), Charset.forName("utf-8")));
//            	builder.addTextBody(key, params.get(key).toString());
            }
            builder.setCharset(Charset.forName("UTF-8"));
            
            HttpEntity hentity = builder.build();  
            httpPost.setEntity(hentity);  
            
            for(String key:headerMap.keySet()){
            	httpPost.setHeader(key, headerMap.get(key).toString());
            }
//            System.out.println("executing request " + httpPost.getRequestLine());
            response = httpClient.execute(httpPost); 
//            log.info("response:"+response.getStatusLine().getStatusCode());
            int statusCode = response.getStatusLine().getStatusCode();  
            if (statusCode != HttpStatus.SC_OK) {  
                return null;  
            }  
            HttpEntity entity = response.getEntity();  
            if (entity == null) {  
                return null;  
            }
            
            content =  getContent(entity);

        } catch (Exception e) {  
            e.printStackTrace();  
        } finally { 
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return content;  
    }
  
    /** 
     * 发送 POST 请求（HTTP），JSON形式 
     * @param apiUrl 
     * @param json json对象 
     * @return 
     */  
    public static String doPost(String apiUrl, Object json) {  
        CloseableHttpClient httpClient = getHttpClient();;  
        String httpStr = null;  
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            StringEntity stringEntity = new StringEntity(json.toString(),"UTF-8");//解决中文乱码问题  
            stringEntity.setContentEncoding("UTF-8");  
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);  
            response = httpClient.execute(httpPost);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doPost statusCode:{},url:{}",statusCode,apiUrl); 
            HttpEntity entity = response.getEntity();  
            httpStr = EntityUtils.toString(entity, "UTF-8");  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            } 
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return httpStr;  
    }  
  
    /** 
     * 发送 POST 请求（HTTP），JSON形式 
     * @param apiUrl 
     * @param json json对象 
     * @return 
     */  
    public static String doPost(String apiUrl, Object json, Map<String,Object> headerMap) {  
        CloseableHttpClient httpClient = getHttpClient();  
        String httpStr = null;  
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            StringEntity stringEntity = new StringEntity(json.toString(),"UTF-8");//解决中文乱码问题  
            stringEntity.setContentEncoding("UTF-8");  
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity); 
            
            if(headerMap!=null) {
            	for(String key:headerMap.keySet()){
            		httpPost.setHeader(key, headerMap.get(key).toString());
            	}
            }
            
            response = httpClient.execute(httpPost);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doPost statusCode:{},url:{}",statusCode,apiUrl); 
            HttpEntity entity = response.getEntity();  
            httpStr = EntityUtils.toString(entity, "UTF-8");  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            } 
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return httpStr;  
    }  
   
    /** 
     * 发送 POST 请求（HTTP），JSON形式 , 代理模式
     * @param apiUrl 
     * @param json json对象 
     * @return 
     */  
    public static String doPost(String apiUrl, String hostName,int port,Object json, Map<String,Object> headerMap) {  
        CloseableHttpClient httpClient  = null;
        if(hostName!=null&&!"".equals(hostName)&&port>0) {
    	    httpClient = HttpClients.custom().setConnectionManager(poolConnManager)
    				.setDefaultRequestConfig(requestConfig).setProxy(new HttpHost(hostName, port)).build();
        } else {
    	    httpClient = getHttpClient();  
        }

        String httpStr = null;  
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            StringEntity stringEntity = new StringEntity(json.toString(),"UTF-8");//解决中文乱码问题  
            stringEntity.setContentEncoding("UTF-8");  
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity); 
            
            if(headerMap!=null) {
            	for(String key:headerMap.keySet()){
            		httpPost.setHeader(key, headerMap.get(key).toString());
            	}
            }
            
            response = httpClient.execute(httpPost);  
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doPost statusCode:{},url:{}",statusCode,apiUrl); 
            HttpEntity entity = response.getEntity();  
            httpStr = EntityUtils.toString(entity, "UTF-8");
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return httpStr;  
    }  
    
    private static String getContent(HttpEntity entity){
    	String content = null;
		try {
			InputStream in = null;  
			Header header = entity.getContentEncoding();  
			if(header != null && header.getValue().equalsIgnoreCase("gzip")){  
			      
			    GzipDecompressingEntity gzipEntity = new GzipDecompressingEntity(entity);  
			    in = gzipEntity.getContent();  
			}else{  
			    in = entity.getContent();  
			}  

			content = getHTMLContent(in);
		} catch (UnsupportedOperationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
        return content;
    }
    
    private static String getHTMLContent(InputStream in) {  
        StringBuffer sb = new StringBuffer();  
        BufferedReader br = new BufferedReader(new InputStreamReader(in));  
        try {  
            String line = null;  
            while((line=br.readLine())!=null){  
                sb.append(line);  
            }  
              
        } catch (IOException e) {  
            e.printStackTrace();  
        }finally{  
            try {  
                br.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
          
        return sb.toString();  
    }  
    
    /** 
     * 发送 SSL GET 请求（HTTPS）
     * @param url API接口URL
     * @return
     */  
    public static String getCookieByGetSsl(String url) {  
        CloseableHttpClient httpClient = HttpClients.custom()
        		.setSSLSocketFactory(createSSLConnSocketFactory())
        		.setConnectionManager(poolConnManager)
        		.setDefaultRequestConfig(requestConfig).build();  
        HttpGet httpGet = new HttpGet(url);  
        CloseableHttpResponse response = null;
  
        try {  
        	httpGet.setConfig(requestConfig);  
            
            response = httpClient.execute(httpGet); 
           int statusCode = response.getStatusLine().getStatusCode();  
           log.info("getCookieByGetSsl statusCode:{},url:{}",statusCode,url); 
           if (statusCode != HttpStatus.SC_OK) {  
                return null;
            }  
            HttpEntity entity = response.getEntity();  
            if (entity == null) {  
                return null;  
            }  
            //System.out.println("content:"+getContent(entity));
            
            Header[] header = response.getHeaders("set-cookie");
            if(header.length>0){
            	return header[0].getValue();
            }
            
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {
        	 if (response != null) {  
                 try {  
                     EntityUtils.consume(response.getEntity());  
                 } catch (IOException e) {  
                     e.printStackTrace();  
                 }  
             } 
             if(httpGet!=null) {
            	 httpGet.releaseConnection();
             }
		} 
        
        return null;  
    }  
    
    /** 
     * 发送 SSL POST 请求（HTTPS），JSON形式 
     * @param apiUrl API接口URL 
     * @param json JSON对象 
     * @return 
     */  
    public static String doPostSSL(String apiUrl, String json,Map<String,Object> headerMap) {  
        CloseableHttpClient httpClient = HttpClients.custom()
        		.setSSLSocketFactory(createSSLConnSocketFactory())
        		.setConnectionManager(poolConnManager)
        		.setDefaultRequestConfig(requestConfig).build();  
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
        String content = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            StringEntity stringEntity = new StringEntity(json.toString(),"UTF-8");//解决中文乱码问题  
//            stringEntity.setContentEncoding("UTF-8");  
            stringEntity.setContentType("application/json");  
            httpPost.setEntity(stringEntity);
            
            for(String key:headerMap.keySet()){
            	httpPost.setHeader(key, headerMap.get(key).toString());
            }
            
            response = httpClient.execute(httpPost); 
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doPostSSL statusCode:{},url:{}",statusCode,apiUrl);  
            if (statusCode != HttpStatus.SC_OK) {  
                return null;  
            }  
            HttpEntity entity = response.getEntity();  
            if (entity == null) {  
                return null;  
            }
            
            content =  getContent(entity);

        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            } 
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return content;  
    }  
  
    /** 
     * 发送  POST 请求（HTTPS/HTTP），JSON形式 ,模拟表单上传文件，multipart/form-data,header内不用再添加content-type
     * @param apiUrl API接口URL 
     * @return
     */  
    public static String doPost(boolean isSSL,String apiUrl,InputStream in, String fileName, Map<String, Object> params, Map<String,Object> headerMap) {  
    	CloseableHttpClient httpClient = null;
    	if(isSSL) {
    		httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
    				.setConnectionManager(poolConnManager)
    				.setDefaultRequestConfig(requestConfig).build();  
    	}else {
    		httpClient = getHttpClient(); 
    	}
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
        String content = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);  
            if(in!=null) {
            	builder.addBinaryBody("file", in, /*ContentType.MULTIPART_FORM_DATA*/
            			ContentType.create("multipart/form-data"), fileName);  
            }
//            builder.addBinaryBody("file", in/*ContentType.MULTIPART_FORM_DATA*/
//               		/* , ContentType.create("multipart/form-data"), fileName*/); 
            
            for (String key : params.keySet()) {
            	builder.addPart(key, new StringBody(params.get(key).toString(), ContentType.TEXT_PLAIN));
//            	builder.addPart(key, new StringBody(params.get(key).toString(), Charset.forName("utf-8")));
//            	builder.addTextBody(key, params.get(key).toString());

            }
//          builder.setCharset(Charset.forName("UTF-8"));
//          builder.setContentType(ContentType.APPLICATION_JSON);
            
            HttpEntity hentity = builder.build();  
            httpPost.setEntity(hentity);  
            
            for(String key:headerMap.keySet()){
            	httpPost.setHeader(key, headerMap.get(key).toString());
            }
            
            response = httpClient.execute(httpPost); 
            int statusCode = response.getStatusLine().getStatusCode();  
            log.info("doPost statusCode:{},url:{}",statusCode,apiUrl); 
            if (statusCode != HttpStatus.SC_OK) {  
                return null;  
            }  
            HttpEntity entity = response.getEntity();  
            if (entity == null) {  
                return null;  
            }
            
            content =  getContent(entity);

        } catch (Exception e) {  
            e.printStackTrace();  
        } finally { 
    	   if (in!= null) {
	        	try {
					in.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
    	   }
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            } 
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return content;  
    }
    
    /** 
     * 发送  POST 请求（HTTPS/HTTP），JSON形式 ,模拟表单上传文件，multipart/form-data,header内不用再添加content-type
     * @param apiUrl API接口URL 
     * @return
     */  
    @SuppressWarnings("deprecation")
	public static String doPost(boolean isSSL,String apiUrl,File file,Map<String, Object> params, Map<String,Object> headerMap) {  
    	CloseableHttpClient httpClient = null;
    	if(isSSL) {
    		httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
    				.setConnectionManager(poolConnManager)
    				.setDefaultRequestConfig(requestConfig).build();  
    	}else {
    		httpClient = getHttpClient(); 
    	}
        HttpPost httpPost = new HttpPost(apiUrl);  
        CloseableHttpResponse response = null;  
        String content = null;  
  
        try {  
            httpPost.setConfig(requestConfig);  
            
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);  
            if(file!=null) {
            	builder.addPart("file", new FileBody(file));
            }
            for (String key : params.keySet()) {
            	builder.addPart(key, new StringBody(params.get(key).toString(), Charset.forName("utf-8")));
//            	builder.addTextBody(key, params.get(key).toString());
            }
            builder.setCharset(Charset.forName("UTF-8"));
            
            HttpEntity hentity = builder.build();  
            httpPost.setEntity(hentity);  
            
            for(String key:headerMap.keySet()){
            	httpPost.setHeader(key, headerMap.get(key).toString());
            }
            response = httpClient.execute(httpPost); 
            log.info("response:"+response.getStatusLine().getStatusCode());
            int statusCode = response.getStatusLine().getStatusCode();  
            if (statusCode != HttpStatus.SC_OK) {  
                return null;  
            }  
            HttpEntity entity = response.getEntity();  
            if (entity == null) {  
                return null;  
            }
            
            content =  getContent(entity);

        } catch (Exception e) {  
            e.printStackTrace();  
        } finally { 
            if (response != null) {  
                try {  
                    EntityUtils.consume(response.getEntity());  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if(httpPost!=null) {
            	httpPost.releaseConnection();
            }
        }  
        return content;  
    }
    
    /** 
     * 创建SSL安全连接 
     * 
     * @return 
     */  
    private static SSLConnectionSocketFactory createSSLConnSocketFactory() {  
        SSLConnectionSocketFactory sslsf = null;  
        try {  
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {  
  
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
                    return true;  
                }  
            }).build();  
            sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {  
  
//                @Override  
                public boolean verify(String arg0, SSLSession arg1) {  
                    return true;  
                }  
  
//                @Override  
                public void verify(String host, SSLSocket ssl) throws IOException {  
                }  
  
//                @Override  
                public void verify(String host, X509Certificate cert) throws SSLException {  
                }  
  
//                @Override  
                public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {  
                }  
            });  
        } catch (GeneralSecurityException e) {  
            e.printStackTrace();  
        }  
        return sslsf;  
    }  
  
  
    /** 
     * 测试方法 
     * @param args 
     */  
    public static void main(String[] args) throws Exception {  
//    	String portal_url = "https://pangolin.bytedance.com/auth/login";
//		String encryPass = "HI2h7E30z6jpE8GF5gE8HqJkG1bbPPRMyDqJekfVdgI/htjtabkrdY4F3M3S+OwX3yfR7+fvavLJUOrbvm6k+1tZRNPpR5tTrF5sU/nMeiFkqBB+C5WhBVQ1X61HJCpV4z7IOEwWAkjaDqJg2NecrSuljySgBpKJJn5ZFCBT+u0=";
//		
////		String cookie = HttpUtil.getCookieByGetSsl(portal_url);
////		System.out.println(cookie);
//		
//		String cookie = "connect.sid=s%3Aw58QjMWVjnPU1TCUGEVkgD73azMECcz7.%2FhKATmv5S65c3IFyJ6%2BXIR1mmCDj6RHy44Z%2BpXCOySI; Path=/; HttpOnly";
//		
//		Map<String, Object> param = new HashMap<String,Object>();
//		param.put("username", "kydsp");
//		param.put("password", encryPass);
//		param.put("captcha", "VZU5");
//		JSONObject json = new JSONObject(param);
//		
//		Map<String, Object> header = new HashMap<String,Object>();
//		header.put("cookie", cookie);
//		
//		String res = HttpPoolUtil.doPostSSL("https://pangolin.bytedance.com/auth/do_login",json.toJSONString(),header);
//		try {
//			JSONObject _json = JSONObject.parseObject(res);
//			System.out.println(_json.getString("message"));
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
    	
    	long start = System.currentTimeMillis();
		String result = HttpPoolUtil.doGet("https://www.bbb.org/", false);
		System.out.println(result);
		long end = System.currentTimeMillis();
		log.info("tbselfMonitoring completed response time:"+(end-start));
		
    }  
}
